#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <string.h>
#include "usart.h"
#include "OLED.h"

#define BUFFER_SIZE   256
#define BUFFER_SIZE_2 256
#define BUFFER_SIZE_3 256

uint8_t TxBuffer[BUFFER_SIZE];
uint8_t TxBuffer_2[BUFFER_SIZE_2];
uint8_t TxBuffer_3[BUFFER_SIZE_3];

uint8_t RxBuffer[BUFFER_SIZE];
uint8_t RxBuffer_2[BUFFER_SIZE];
uint8_t RxBuffer_3[BUFFER_SIZE_3];

uint8_t receivedByte;
uint8_t receivedByte_2;
uint8_t receivedByte_3;

uint8_t Serial_RxFlag;
uint8_t Serial_RxFlag2;
uint8_t Serial_RxFlag3;

uint8_t rx_index  = 0;
uint8_t rx_index2 = 0;
uint8_t rx_index3 = 0;

uint8_t cmd_received  = 0; // 指令接收完成标志
uint8_t cmd_received2 = 0; // 指令接收完成标志
uint8_t cmd_received3 = 0; // 指令接收完成标志

SpitballCoordinates SpitballCoordinates_data;

// 指令协议配置
#define MAX_CMD_LEN     16   // 最大指令长度
#define CMD_TERMINATOR  '\n' // 指令结束符
#define HEX_PREFIX      "0x" // 十六进制前缀

#define FRAME_HEADER1_2 0xAA // 帧头
#define FRAME_HEADER2_2 0x55
#define FRAME_TAIL_2    0xFF // 帧尾

typedef struct {
    const char *cmd_str; // 指令字符串
    uint8_t cmd_id;      // 指令编号
    // uint32_t param;      // 参数存储
} CmdMapping;

static const CmdMapping cmd_table[] = {
    {"FWD", 1}, // 前进指令 示例: "FWD 100"
    {"BCK", 2}, // 后退指令 示例: "BCK 50"
    {"TUL", 3}, // 左转指令
    {"TUR", 4}, // 右转指令
    {"PNK", 5}, // 粉色触发
    {"RED", 6}, // 红色触发

    {"LSP", 7}, // 低速指令
    {"MSP", 8}, // 中速指令
    {"HSP", 9}, // 高速指令

    {"GSP", 10}, // 抓取指令

    {"STP", 11}, // 停止指令

    {"POS", 12}, // 定位指令

    {"RES", 13}, // 复位指令
};

void Usart1_Init()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // tx
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // rx
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate            = 9600;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_Init(USART1, &USART_InitStructure);

    /*中断输出配置*/
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接收数据的中断

    /*NVIC中断分组*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置NVIC为分组2

    /*NVIC配置*/
    NVIC_InitTypeDef NVIC_InitStructure;                                // 定义结构体变量
    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn; // 选择配置NVIC的USART1线
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // 指定NVIC线路使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           // 指定NVIC线路的抢占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;           // 指定NVIC线路的响应优先级为1
    NVIC_Init(&NVIC_InitStructure);                                     // 将结构体变量交给NVIC_Init，配置NVIC外设

    USART_Cmd(USART1, ENABLE);
}

void Usart1_SendByte(uint8_t Byte)
{
    USART_SendData(USART1, Byte);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

uint8_t Serial_GetRxFlag(void)
{
    if (Serial_RxFlag == 1) // 如果标志位为1
    {
        Serial_RxFlag = 0;
        return 1; // 则返回1，并自动清零标志位
    }
    return 0; // 如果标志位为0，则返回0
}

/**
 * 函    数：获取串口接收的数据
 * 参    数：无
 * 返 回 值：接收的数据，范围：0~255
 */
uint8_t Usart1_GetRxData(void)
{
    return RxBuffer; // 返回接收的数据变量
}

void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) // 判断是否是USART1的接收事件触发的中断
    {

        receivedByte = USART_ReceiveData(USART1);
        if (rx_index < RxBuffer - 1) {
            RxBuffer[rx_index++] = receivedByte;
            if (receivedByte == '\n') {    // 假设以换行符作为指令结束标志
                RxBuffer[rx_index] = '\0'; // 添加字符串结束符
                cmd_received       = 1;    // 标记指令接收完成
                rx_index           = 0;    // 清空缓冲区
            }
            Serial_RxFlag = 1;                              // 置接收标志位变量为1
            USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除USART1的RXNE标志位
                                                            // 读取数据寄存器会自动清除此标志位
                                                            // 如果已经读取了数据寄存器，也可以不执行此代码
        }
    }
}

void Usart2_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // tx
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2; // 根据实际连接修改
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // rx
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3; // 根据实际连接修改
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate            = 115200;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_Init(USART2, &USART_InitStructure);

    /*中断输出配置*/
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 开启串口接收数据的中断

    /*NVIC中断分组*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置NVIC为分组2

    /*NVIC配置*/
    NVIC_InitTypeDef NVIC_InitStructure;                                // 定义结构体变量
    NVIC_InitStructure.NVIC_IRQChannel                   = USART2_IRQn; // 选择配置NVIC的USART2线
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // 指定NVIC线路使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           // 指定NVIC线路的抢占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;           // 指定NVIC线路的响应优先级为1
    NVIC_Init(&NVIC_InitStructure);                                     // 将结构体变量交给NVIC_Init，配置NVIC外设

    USART_Cmd(USART2, ENABLE);
}

void Usart2_SendByte(uint8_t Byte)
{
    USART_SendData(USART2, Byte);
    while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}

uint8_t Usart2_GetRxData(void)
{
    return RxBuffer_2; // 返回接收的数据变量
}

void USART2_IRQHandler(void)
{
    if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) // 判断接收中断
    {
        receivedByte_2 = USART_ReceiveData(USART2);

        if (rx_index2 < BUFFER_SIZE_2 - 1) // 保留1字节给'\0'
        {
            RxBuffer_2[rx_index2++] = receivedByte_2;

            if (receivedByte_2 == '\n') // 检测到换行符
            {
                RxBuffer_2[rx_index2] = '\0'; // 添加字符串结束符
                cmd_received2         = 1;    // 标记接收完成
                rx_index2             = 0;    // 重置缓冲区指针
            }
        } else {
            rx_index2 = 0; // 缓冲区溢出，重置
        }

        USART_ClearITPendingBit(USART2, USART_IT_RXNE); // 清除中断标志
    }
}

void Usart3_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // tx
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10; // 根据实际连接修改
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // rx
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11; // 根据实际连接修改
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate            = 9600;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_Init(USART3, &USART_InitStructure);

    /*中断输出配置*/
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 开启串口接收数据的中断

    /*NVIC中断分组*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置NVIC为分组2

    /*NVIC配置*/
    NVIC_InitTypeDef NVIC_InitStructure;                                // 定义结构体变量
    NVIC_InitStructure.NVIC_IRQChannel                   = USART3_IRQn; // 选择配置NVIC的USART3线
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // 指定NVIC线路使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           // 指定NVIC线路的抢占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;           // 指定NVIC线路的响应优先级为1
    NVIC_Init(&NVIC_InitStructure);                                     // 将结构体变量交给NVIC_Init，配置NVIC外设

    USART_Cmd(USART3, ENABLE);
}

void Usart3_SendByte(uint8_t Byte)
{
    USART_SendData(USART3, Byte);
    while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}

void USART3_IRQHandler(void)
{
    if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) // 判断接收中断
    {
        receivedByte = USART_ReceiveData(USART3);

        if (rx_index3 < BUFFER_SIZE_3 - 1) // 保留1字节给'\0'
        {
            RxBuffer_3[rx_index3++] = receivedByte;

            if (receivedByte == '\n') // 检测到换行符
            {
                RxBuffer_3[rx_index3] = '\0'; // 添加字符串结束符
                cmd_received3         = 1;    // 标记接收完成
                rx_index3             = 0;    // 重置缓冲区指针
            }
        } else {
            rx_index3 = 0; // 缓冲区溢出，重置
        }

        USART_ClearITPendingBit(USART3, USART_IT_RXNE); // 清除中断标志
    }
}

// 串口指令解析获取
int parse_serial_command(void)
{
    if (!cmd_received) return -1;

    char cmd_str[MAX_CMD_LEN];
    strncpy(cmd_str, (char *)RxBuffer, MAX_CMD_LEN);
    memset(RxBuffer, 0, sizeof(RxBuffer));
    // 字符串指令匹配
    for (int i = 0; i < sizeof(cmd_table) / sizeof(CmdMapping); i++) {
        if (strncmp(cmd_str, cmd_table[i].cmd_str, strlen(cmd_table[i].cmd_str)) == 0) {
            // 参数提取（示例："FWD 100" → param=100）
            // extract_parameters(cmd_str, &cmd_table[i]);
            return cmd_table[i].cmd_id;
        }
    }

    cmd_received = 0;
    return -1; // 无效指令
}

// // 参数提取函数
// static void extract_parameters(char *cmd, CmdMapping *entry)
// {
//     char *param_start = strchr(cmd, ' ');
//     if (param_start) {
//         entry->param = atoi(param_start + 1);
//     }
// }
/*
int handle_serial_command()
{
    if (cmd_received) {
        if (RxBuffer[0] == 'F') { // 前进
            return 1;
        } else if (RxBuffer[0] == 'B') { // 后退
            return 2;
        } else if (RxBuffer[0] == 'L') { // 左转
            return 3;
        } else if (RxBuffer[0] == 'R') { // 右转
            return 4;
        } else if (RxBuffer[0] == 'p') { //
            return 5;
        } else if (RxBuffer[0] == 'r') { //
            return 6;
        } else if (RxBuffer[0] == 'S') { //
            return 7;
        }
        cmd_received = 0; // 清除指令接收完成标志
    }
}

int Robot_serial_command()
{
    if (cmd_received) {
        if (RxBuffer[0] == 'U') { // 前进
            return 1;
        } else if (RxBuffer[0] == 'D') { // 后退
            return 2;
        } else if (RxBuffer[0] == 'F') { // 左转
            return 3;
        } else if (RxBuffer[0] == 'B') { // 右转
            return 4;
        } else if (RxBuffer[0] == 'O') { //
            return 5;
        } else if (RxBuffer[0] == 'C') { //
            return 6;
        } else if (RxBuffer[0] == 'S') { //
            return 7;
        }
        cmd_received = 0; // 清除指令接收完成标志
    }
}*/

SpitballCoordinates Get_Spitball_Coordinates(void)
{
    if (cmd_received2) {
        sscanf((char *)RxBuffer_2, "%d,%d,%d", &SpitballCoordinates_data.x, &SpitballCoordinates_data.y, &SpitballCoordinates_data.s); // 解析坐标

        // 打印接收到的数据
        printf("Received: %d %d %d\r\n", SpitballCoordinates_data.x, SpitballCoordinates_data.y, SpitballCoordinates_data.s);
        OLED_ShowNum(1, 3, SpitballCoordinates_data.x, 3);
        OLED_ShowNum(2, 3, SpitballCoordinates_data.y, 3);
        OLED_ShowNum(3, 3, SpitballCoordinates_data.s, 5);
        cmd_received2 = 0;
        return SpitballCoordinates_data;
    } else { 
        // printf("Received: 00,00\r\n");
        return SpitballCoordinates_data;
    }
}

int fputc(int ch, FILE *f)
{
    Usart1_SendByte((uint8_t)ch);
    return ch;
}
